package cn.planewar;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Arrays;
import java.util.Random;
import javax.swing.JPanel;
import javax.swing.JFrame;
import java.awt.Graphics;
import java.util.Timer;
import java.util.TimerTask;

public class World extends JPanel{
    public static final int WIDTH = 420;
    public static final int HEIGHT = 700;
    private static int score = 0;

    private static final int START = 0;
    private static final int RUNNING = 1;
    private static final int PAUSE = 2;
    private static final int GAME_OVER = 3;
    private static int state = START;

    private Sky[] sky = {new Sky(0),new Sky(-HEIGHT)};
    private Hero hero = new Hero();
    private SkyObject[] hostilityPlanes = {};
    private Bullet[] bullets = {};
    private Bom[] boms = {};

    private int initiativeskyobj = 0;
    private void skyObjectEnterIndex(){
        initiativeskyobj++;
        if (initiativeskyobj%60 == 0) {
            Random rand = new Random();
            int num = rand.nextInt(20);
            if (num>9) {
                hostilityPlanes = Arrays.copyOf(hostilityPlanes,hostilityPlanes.length+1);
                hostilityPlanes[hostilityPlanes.length-1] = new LittleHostilityPlane();
            }
            if (num>2) {
                hostilityPlanes = Arrays.copyOf(hostilityPlanes,hostilityPlanes.length+1);
                hostilityPlanes[hostilityPlanes.length-1] = new BigHostilityPlane();
            } else {
                hostilityPlanes = Arrays.copyOf(hostilityPlanes,hostilityPlanes.length+1);
                hostilityPlanes[hostilityPlanes.length-1] = new Bee();
            }
        }
    }

    private int initiativebullet = 0;
    private void heroFire(){
        initiativebullet++;
        if (initiativebullet%30==0){
            switch (hero.showFire()){
                case 1:
                    bulletEnterIndex(hero.getX()+hero.getWidth()/2-4,hero.getY()+40);
                    break;
                case 2:
                    bulletEnterIndex(hero.getX()+hero.getWidth()/2-4-15,hero.getY()+60);
                    bulletEnterIndex(hero.getX()+hero.getWidth()/2-4+15,hero.getY()+60);
                    break;
                case 3:
                    bulletEnterIndex(hero.getX()+hero.getWidth()/2-4,hero.getY()+40);
                    bulletEnterIndex(hero.getX()+hero.getWidth()/2-4-25,hero.getY()+60);
                    bulletEnterIndex(hero.getX()+hero.getWidth()/2-4+25,hero.getY()+60);
                    break;
            }
        }
    }

    private void bulletEnterIndex(int x,int y){
        bullets = Arrays.copyOf(bullets,bullets.length+1);
        bullets[bullets.length-1]=hero.shootBullet(x,y);
    }

    private void bomEnterIndex(int x,int y){
        boms = Arrays.copyOf(boms,boms.length+1);
        boms[boms.length-1] = new Bom(x,y);
    }

    private int initiativeskyMove = 0;
    private void skyObjectMove(){
        initiativeskyMove++;
        if (initiativeskyMove%2==0){
            for (int i = 0;i<sky.length;i++) {
                sky[i].step();
            }
        }
        for (int i = 0;i<hostilityPlanes.length;i++) {
            if (hostilityPlanes[i].isLive()) {
                hostilityPlanes[i].step();
            }
        }
        for (int i = 0;i<bullets.length;i++) {
            bullets[i].step();
        }
        for (int i = 0;i<boms.length;i++) {
            boms[i].setObjstate(boms[i].getObjstate()+1);
        }
    }

    private void objectStateChange(){
        for (int i = 0;i<hostilityPlanes.length;i++) {
            if (hostilityPlanes[i] instanceof LittleHostilityPlane){
                hostilityPlanes[i].powerChange();
            } else {
                hostilityPlanes[i].stateChange();
            }
        }
        ((SkyObject)(hero)).powerChange();
    }

    private void getAwary(int i) {
        if (hostilityPlanes[i] instanceof EnemyScore) {
            score += ((EnemyScore) (hostilityPlanes[i])).getScore();
        } else if (hostilityPlanes[i] instanceof Bee) {
            if (((Bee) (hostilityPlanes[i])).getAwardType() == 0) {
                if (hostilityPlanes[i] instanceof EnemyLife) {
                    hero.addLife(((EnemyLife) (hostilityPlanes[i])).getLife());
                }
            } else if (((Bee) (hostilityPlanes[i])).getAwardType() == 1) {
                if (hostilityPlanes[i] instanceof EnemyFire) {
                    hero.addFire(((EnemyFire) (hostilityPlanes[i])).getFire());
                }
            }
        }
    }

    private void bulletHitAction(){
        for (int i=0;i<bullets.length;i++) {
            for (int j=0;j<hostilityPlanes.length;j++) {
                if (bullets[i].isHit(hostilityPlanes[j]) && bullets[i].isLive() && hostilityPlanes[j].isLive()) {
                    bullets[i].goDead();
                    hostilityPlanes[j].goDead();
                    bomEnterIndex(hostilityPlanes[j].getX()+ hostilityPlanes[j].getWidth()/2-21,hostilityPlanes[j].getY()+ hostilityPlanes[j].getHeight()/2-18);
                    getAwary(j);
                }
            }
        }
    }

    private void heroHitAction(){
        for (int i = 0;i<hostilityPlanes.length;i++) {
            if (hero.isHit(hostilityPlanes[i]) && hostilityPlanes[i].isLive()){
                hostilityPlanes[i].goDead();
                bomEnterIndex(hostilityPlanes[i].getX()+ hostilityPlanes[i].getWidth()/2-21,hostilityPlanes[i].getY()+ hostilityPlanes[i].getHeight()/2-18);
                hero.loseLife();
                hero.clearFire();
            }
        }
    }

    private void outOfBounds(){
        for (int i = 0;i<sky.length;i++){
            if (sky[i].getY()>=HEIGHT){
                sky[i].setY(-HEIGHT);
                System.out.println(sky[i].getY());
            }
        }
        for (int i = 0;i<hostilityPlanes.length;i++){
            if (hostilityPlanes[i].isDead()) {
                hostilityPlanes[i].deadTimer();
                if (hostilityPlanes[i].getY()>=HEIGHT || hostilityPlanes[i].getDeadTime()>=25){
                    hostilityPlanes[i]=hostilityPlanes[hostilityPlanes.length-1];
                    hostilityPlanes = Arrays.copyOf(hostilityPlanes,hostilityPlanes.length-1);
                }
            }
        }
        for (int i = 0;i<bullets.length;i++){
            if (bullets[i].getY()<0 || bullets[i].isDead()){
                bullets[i]=bullets[bullets.length-1];
                bullets = Arrays.copyOf(bullets,bullets.length-1);
            }
        }
        for (int i = 0;i<boms.length;i++){
            if (boms[i].getObjstate()>=25) {
                boms[i]=boms[boms.length-1];
                boms = Arrays.copyOf(boms,boms.length-1);
            }
        }
    }

    private void stateChangeGameOver(){
        if (hero.showLife()<=0){
            state = GAME_OVER;
        }
    }
    private void stateChangeRunning(){
        state = RUNNING;
    }
    private void stateChangePause(){
        if (state==RUNNING){
            state = PAUSE;
        } else if (state==PAUSE){
            state = RUNNING;
        }
    }

    private int gameOver = 0;
    private void stateChangeStart() {
        if (state==GAME_OVER) {
            gameOver++;
        }
        if (gameOver >= 1000) {
            state = START;
            for (int i = hostilityPlanes.length; i > 0; i--) {
                hostilityPlanes = Arrays.copyOf(hostilityPlanes, hostilityPlanes.length - 1);
            }
            for (int i = bullets.length; i > 0; i--) {
                bullets = Arrays.copyOf(bullets, bullets.length - 1);
            }
            for (int i = boms.length; i > 0; i--) {
                boms = Arrays.copyOf(boms, boms.length - 1);
            }
            hero.newGame();
            score = 0;
        }
    }

    private void action(){
        KeyAdapter k= new KeyAdapter() {
            @Override
            public void keyReleased(KeyEvent e) {
                if (e.getKeyCode()==KeyEvent.VK_P) {
                    stateChangePause();
                }
                if (e.getKeyCode()==KeyEvent.VK_SPACE) {
                    if (state==GAME_OVER||state==START) {
                        stateChangeRunning();
                    }
                }
            }
        };
        this.addKeyListener(k);

        MouseAdapter m = new MouseAdapter() {
            @Override
            public void mouseMoved(MouseEvent e) {
                if (state==RUNNING) {
                    hero.setX(e.getX()-49);
                    hero.setY(e.getY()-70);
                }
            }
        };
        this.addMouseListener(m);
        this.addMouseMotionListener(m);

        Timer timer = new Timer();
        int interval =10;
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                if (state==GAME_OVER){
                    stateChangeStart();
                    repaint();
                }
                if (state==RUNNING) {
                    skyObjectEnterIndex();
                    heroFire();
                    skyObjectMove();
                    objectStateChange();
                    heroHitAction();
                    bulletHitAction();
                    outOfBounds();
                    stateChangeGameOver();
                    repaint();
                }
            }
        },interval,interval);
    }

    public void paint(Graphics g){
        for (int i = 0;i<sky.length;i++) {
            sky[i].paintImage(g);
        }
        for (int i = 0;i< hostilityPlanes.length;i++) {
            hostilityPlanes[i].paintImage(g);
        }
        for (int i = 0;i<bullets.length;i++) {
            bullets[i].paintImage(g);
        }
        hero.paintImage(g);
        for (int i = 0;i<boms.length;i++) {
            boms[i].paintImage(g);
        }
        g.drawString("SCORE: "+score,25,25);
        g.drawString("LIFE:  "+hero.showLife(),25,45);
        if (state == START) {
            Image.start.paintIcon(null, g, 0, 0);
        } else if (state == PAUSE) {
            Image.pause.paintIcon(null,g,0,0);
        } else if (state == GAME_OVER) {
            Image.gameover.paintIcon(null,g,0,0);
        }
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame();
        World world = new World();
        world.setFocusable(true);
        frame.add(world);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(WIDTH+6,HEIGHT+29);
        frame.setLocationRelativeTo(null);
        frame.setResizable(false);
        frame.setVisible(true);

        world.action();
    }
}
